import {
	IParam,
	IChartControllerParams,
	ICtrlActionResult,
} from '@/core/interface';
import { IChartAbility } from '@/core/interface/widgets/ability';
import { IChartController } from '@/core/interface/widgets/controller';
import { ChartActionType } from '@/core/interface/widgets/event';
import { IChartStore } from '@/core/interface/widgets/store';
import { ControlVOBase } from '@/core/modules';
import ChartService from '@/core/modules/ctrl-service/chart-service';
import { createUUID, deepCopy, deepObjectMerge } from '@/core/utils';
import { init } from 'echarts';
import moment from 'moment';
import { MDCtrlControllerBase } from './md-ctrl-controller-base';

/**
 * 图表控制器
 *
 * @export
 * @class ChartController
 * @extends {(MDCtrlController<T | ChartActionType, IChartStore, IChartAbility>)}
 * @implements {IChartController<T>}
 * @template A
 */
export class ChartController
	extends MDCtrlControllerBase<ChartActionType, IChartStore, IChartAbility>
	implements IChartController<IChartStore, IChartAbility>
{
	/**
	 * 图表部件服务
	 *
	 * @protected
	 * @type {ChartService<ControlVOBase>}
	 * @memberof ChartController
	 */
	protected declare ctrlService: ChartService<ControlVOBase>;

	/**
	 * echarts图表对象
	 *
	 * @memberof ChartController
	 */
	public myChart: any;

	/**
	 * 前端组装的序列模型
	 *
	 * @memberof ChartController
	 */
	public seriesModel: IParam = {};

	/**
	 * 初始图表所需参数
	 *
	 * @memberof ChartController
	 */
	protected chartOption: IParam = {};

	/**
	 * 图表自定义参数集合
	 *
	 * @memberof ChartController
	 */
	public chartUserParams: IParam = {};

	/**
	 * 图表基础动态模型
	 *
	 * @memberof ChartController
	 */
	public chartBaseOPtion: IParam = {};

	/**
	 * 图表值属性
	 *
	 * @memberof ChartController
	 */
	public chartValueName: string = '';

	/**
	 * 图表分类属性
	 *
	 * @memberof ChartController
	 */
	public chartCatalogName: string = '';

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {IChartControllerParams<ChartActionType, IChartAbility>} params
	 * @memberof ChartController
	 */
	protected processCtrlInit(
		params: IChartControllerParams<ChartActionType, IChartAbility>
	) {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			isNoData: false,
			chartId: createUUID(),
			chartRenderOption: {},
		});
		this.initSeriesModel();
		this.initChartOption();
		this.initChartUserParams();
		this.initChartBaseOPtion();
	}

	/**
	 * 图表数据加载
	 *
	 * @param {IParam} [opts={}]
	 * @param {boolean} [pageReset=false]
	 * @return {*}  {Promise<IHttpResponse>}
	 * @memberof ChartController
	 */
	public async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const res = await super.load(opts);
		const _this = this;
		this.transformToBasicChartSetData(this.store.data, (codelist: any) => {
			_this.drawCharts();
		});
		return res;
	}

	/**
	 * 处理加载数据变更
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof ChartController
	 */
	protected handleLoadDataChange(data: IParam[]): void {
		this.store.data = data;
	}

	/**
	 * 绘制图表
	 *
	 * @returns {*}
	 * @memberof ChartController
	 */
	public drawCharts() {
		if (!this.myChart) {
			let element: any = document.getElementById(this.store.chartId);
			if (element) {
				this.myChart = init(element);
			}
		}
		//判断刷新时dom是否存在
		if (
			this.myChart &&
			!Object.is(this.myChart._dom.offsetHeight, 0) &&
			!Object.is(this.myChart._dom.offsetWidth, 0)
		) {
			let _chartOption = this.handleChartOPtion();
			this.store.chartRenderOption = { ..._chartOption };
			if (this.myChart) {
				this.myChart.setOption(_chartOption);
				this.onChartEvents();
				this.handleDefaultSelect();
				this.myChart.resize();
			}
		}
	}

	/**
	 * 图表事件监听
	 *
	 * @memberof ChartController
	 */
	public onChartEvents() {
		this.myChart?.on('click', (e: any) => {
			this.onChartClick(e);
		});
		this.myChart?.on('selectchanged', (e: any) => {
			if (this.selectFirstDefault) {
				if (e && e.fromActionPayload) {
					const _event = {
						seriesId: e.fromActionPayload.seriesId,
						data: e.fromActionPayload.curData,
						name: e.fromActionPayload.seriesId,
					};
					this.onChartClick(_event);
				}
			}
		});
	}

	/**
	 * 图表单击事件
	 *
	 * @memberof ChartControlBase
	 */
	public onChartClick(event: any) {
		if (!event || !event.name) {
			return;
		}
		let data: any = event.data;
		Object.assign(data, { _chartName: event.seriesId });
		this.store.selections = [data];
		this.emit('selectionChange', [data]);
	}

	/**
	 * 处理默认选中
	 *
	 * @memberof ChartController
	 */
	public handleDefaultSelect() {
		if (this.selectFirstDefault) {
			const options = this.handleChartOPtion();
			const selectSeriesId = this.model.serieses?.[0]?.name || null;
			const curData = options?.dataset[0]?.source?.[0] || undefined;
			if (selectSeriesId && curData) {
				this.myChart?.dispatchAction({
					type: 'select',
					seriesId: selectSeriesId.toLowerCase(),
					dataIndex: 0,
					curData: curData,
				});
			}
		}
	}

	/**
	 * 处理图表参数
	 *
	 * @memberof ChartController
	 */
	public handleChartOPtion() {
		let _chartOption: any = deepCopy(this.chartOption);
		if (Object.keys(this.seriesModel).length > 0) {
			let tempDataSourceMap: Map<string, any> = new Map();
			for (let i = 0; i < Object.keys(this.seriesModel).length; i++) {
				Object.values(this.seriesModel).forEach((seriesvalue: any) => {
					if (seriesvalue.seriesIndex === i) {
						tempDataSourceMap.set(seriesvalue.name, seriesvalue.data);
					}
				});
			}
			if (tempDataSourceMap.size > 0) {
				tempDataSourceMap.forEach((item: any) => {
					_chartOption.dataset.push({ source: item });
				});
			}
			Object.keys(this.seriesModel).forEach((seriesName: string) => {
				if (_chartOption && _chartOption.series.length > 0) {
					_chartOption.series.forEach((item: any) => {
						if (
							this.seriesModel[seriesName].ecxObject &&
							Object.is(seriesName, item.id)
						) {
							item = deepObjectMerge(
								item,
								this.seriesModel[seriesName].ecxObject
							);
						}
						if (
							this.seriesModel[seriesName].baseOption &&
							Object.keys(this.seriesModel[seriesName].baseOption).length > 0 &&
							Object.is(seriesName, item.id)
						) {
							item = deepObjectMerge(
								item,
								this.seriesModel[seriesName].baseOption
							);
						}
						if (
							this.seriesModel[seriesName].ecObject &&
							Object.is(seriesName, item.id)
						) {
							item = deepObjectMerge(
								item,
								this.seriesModel[seriesName].ecObject
							);
						}
					});
				}
				//设置多序列
				let tempSeries: any = this.seriesModel[seriesName];
				const returnIndex: number = _chartOption.series.findIndex(
					(item: any) => {
						return Object.is(item.id, seriesName);
					}
				);
				if (tempSeries && Object.is(tempSeries.type, 'gauge')) {
					_chartOption.series.splice(returnIndex, 1);
					const maxValue: number = this.calcSourceMaxValue(
						_chartOption.dataset[0].source
					);
					let temSeries = {
						type: 'gauge',
						title: {
							fontSize: 14,
						},
						progress: {
							show: true,
							overlap: false,
							roundCap: true,
						},
						max: maxValue,
						detail: {
							width: 40,
							height: 14,
							fontSize: 14,
							color: '#fff',
							backgroundColor: 'auto',
							borderRadius: 3,
							formatter: '{value}',
						},
						data: this.transformToChartSeriesData(
							_chartOption.dataset[0].source,
							'gauge'
						),
					};
					_chartOption.series.push(temSeries);
				} else if (tempSeries && Object.is(tempSeries.type, 'radar')) {
					const maxValue: number = this.calcSourceMaxValue(
						_chartOption.dataset[0].source
					);
					_chartOption.radar.indicator?.forEach((item: any) => {
						item.max = item.max ? item.max : maxValue;
					});
					_chartOption.series[returnIndex].data =
						this.transformToChartSeriesData(
							_chartOption.dataset[0].source,
							'radar',
							_chartOption.radar.indicator
						);
				} else if (tempSeries && Object.is(tempSeries.type, 'candlestick')) {
					_chartOption.series[returnIndex].data =
						this.transformToChartSeriesData(
							_chartOption.dataset[0].source,
							'candlestick'
						);
				} else if (
					tempSeries &&
					tempSeries.seriesIdField &&
					tempSeries.seriesValues.length > 0
				) {
					let series = _chartOption.series[returnIndex];
					_chartOption.series.splice(returnIndex, 1);
					delete series.id;
					tempSeries.seriesValues.forEach((seriesvalueItem: any) => {
						let tempSeriesTemp: any = deepCopy(tempSeries.seriesTemp);
						Object.assign(tempSeriesTemp, series);
						tempSeriesTemp.name = tempSeries.seriesMap[seriesvalueItem];
						tempSeriesTemp.datasetIndex = tempSeries.seriesIndex;
						tempSeriesTemp.encode = {
							x: tempSeries.categorField,
							y: `${seriesvalueItem}`,
						};
						_chartOption.series.push(tempSeriesTemp);
					});
				}
			});
		}
		if (Object.keys(this.chartBaseOPtion).length > 0) {
			Object.assign(_chartOption, this.chartBaseOPtion);
		}
		if (Object.keys(this.chartUserParams).length > 0) {
			Object.assign(_chartOption, this.chartUserParams);
		}
		return _chartOption;
	}

	/**
	 *
	 * 计算数据集最大数
	 *
	 * @param {Array<any>} data 传入数据
	 * @memberof ChartController
	 */
	public calcSourceMaxValue(source: any[]) {
		let data: any[] = [];
		source.forEach((item: any) => {
			if (item.data) {
				data.push(item.data);
			} else {
				let itemData = [];
				for (const key in item) {
					if (!isNaN(item[key])) {
						itemData.push(item[key]);
					}
				}
				data.push(Math.max(...itemData));
			}
		});
		return Math.max(...data);
	}

	/**
	 *
	 * 1.整合数据集数据到data中，不走数据集
	 *
	 * @param {Array<any>} data 传入数据
	 * @param {Array<any>} series chart类型
	 * @memberof ChartControlBase
	 */
	public transformToChartSeriesData(
		source: any[],
		series: string,
		indicator?: any[]
	) {
		if (Object.is(series, 'gauge')) {
			let seriesData: any[] = [];
			let offsetLength: number = 100 / (source.length - 1);
			source.forEach((sourceItem: any, index: number) => {
				let data = {
					name: sourceItem[this.chartCatalogName],
					value: sourceItem[this.chartValueName],
					title: {
						offsetCenter: [index * offsetLength - 50 + '%', '80%'],
					},
					detail: {
						offsetCenter: [index * offsetLength - 50 + '%', '95%'],
					},
				};
				seriesData.push(data);
			});
			return seriesData;
		} else if (Object.is(series, 'radar')) {
			if (!indicator || indicator.length == 0) {
				console.log(
					App.ts(
						'widget.chart.noindicator',
						'雷达图indicator不存在，无法转换数据集！'
					)
				);
				return;
			}
			let seriesData: any[] = [];
			source.forEach((sourceItem: any) => {
				let name = sourceItem.type;
				let data: any[] = [];
				indicator.forEach((item: any) => {
					data.push(sourceItem[item.name]);
				});
				seriesData.push({ name, value: data });
			});
			return seriesData;
		} else if (Object.is(series, 'candlestick')) {
			let seriesData: any[] = [];
			source.forEach((sourceItem: any) => {
				let name = sourceItem.type;
				seriesData.push({ name, value: sourceItem[this.chartValueName] });
			});
			return seriesData;
		}
	}

	/**
	 * 获取图表所需代码表
	 *
	 * @memberof ChartController
	 */
	public getChartAllCodeList(): Promise<any> {
		return new Promise((resolve: any, reject: any) => {
			let codeListMap: Map<string, any> = new Map();
			if (Object.values(this.seriesModel).length > 0) {
				let tempFlag: boolean = true;
				Object.values(this.seriesModel).forEach((singleSeries: any) => {
					if (
						singleSeries.dataSetFields &&
						singleSeries.dataSetFields.length > 0
					) {
						let promiseArray: Array<any> = [];
						let promiseKeyArray: Array<any> = [];
						singleSeries.dataSetFields.forEach(
							(singleDataSetField: any, index: any) => {
								if (singleDataSetField.codelist) {
									tempFlag = false;
									if (!codeListMap.get(singleDataSetField.codelist.codeName)) {
										promiseArray.push(
											this.getCodeList(singleDataSetField.codelist)
										);
										promiseKeyArray.push(singleDataSetField.codelist.codeName);
										Promise.all(promiseArray).then((result: any) => {
											if (result && result.length > 0) {
												result.forEach((codeList: any) => {
													let tempCodeListMap: Map<number, any> = new Map();
													if (codeList.length > 0) {
														codeList.forEach((codeListItem: any) => {
															tempCodeListMap.set(
																codeListItem.value,
																codeListItem.text
															);
														});
													}
													codeListMap.set(
														singleDataSetField.codelist.codeName,
														tempCodeListMap
													);
												});
												resolve(codeListMap);
											}
										});
									}
								}
							}
						);
					}
				});
				if (tempFlag) {
					resolve(codeListMap);
				}
			} else {
				resolve(codeListMap);
			}
		});
	}

	/**
	 * 获取代码表
	 *
	 * @param {*} codeListObject 代码表对象
	 * @return {*}  {Promise<any>}
	 * @memberof ChartController
	 */
	public getCodeList(codeListObject: any): Promise<any> {
		return new Promise((resolve: any, reject: any) => {
			App.getAppCodeListHelper()
				.getCodeListItems(
					codeListObject.codeListTag,
					this.store.context,
					this.store.viewParams
				)
				.then((res: any) => {
					resolve(res.data);
				})
				.catch((error: any) => {
					console.log(
						`----${codeListObject.codeName}----${App.ts(
							'common.generic.codenotexist',
							'代码表不存在'
						)}`
					);
				});
		});
	}

	/**
	 * 实体数据集转化为图表数据集
	 *
	 * 1.获取图表所有代码表值
	 * 2.查询集合映射图表数据集
	 * 3.补全图表数据集
	 * 4.图表数据集分组求和
	 * 5.排序图表数据集
	 *
	 * @param {*} data 实体数据集
	 * @param {Function} callback 回调
	 * @memberof ChartController
	 */
	public async transformToBasicChartSetData(data: any, callback: Function) {
		if (!data || !Array.isArray(data) || data.length === 0) {
			this.store.isNoData = true;
			if (this.myChart) {
				this.myChart.dispose();
				this.myChart = undefined;
			}
			return;
		}
		this.store.isNoData = false;
		//获取代码表值
		let allCodeList: any = await this.getChartAllCodeList();
		if (Object.values(this.seriesModel).length > 0) {
			Object.values(this.seriesModel).forEach(
				(singleSeries: any, index: number) => {
					// 值属性为srfcount设置{srfcount:1}到data
					let valueField = singleSeries.dataSetFields.find(
						(datasetField: any) => {
							return datasetField.name === singleSeries.valueField;
						}
					);
					if (
						valueField &&
						valueField.name &&
						Object.is(valueField.name, 'srfcount')
					) {
						data.forEach((singleData: any) => {
							Object.assign(singleData, { srfcount: 1 });
						});
					}
					// 分组属性
					let groupField = singleSeries.dataSetFields.find(
						(datasetField: any) => {
							return datasetField.name === singleSeries.categorField;
						}
					);
					let tempChartSetData: Array<any> = [];
					let tempSeriesValues: Map<string, any> = new Map();
					data.forEach((item: any) => {
						let tempChartSetDataItem: any = {};
						// 序列属性不存在
						if (!singleSeries.seriesIdField) {
							Object.assign(tempChartSetDataItem, { name: singleSeries.name });
							if (
								singleSeries.dataSetFields &&
								singleSeries.dataSetFields.length > 0
							) {
								singleSeries.dataSetFields.forEach(
									(singleDataSetField: any) => {
										this.handleSingleDataSetField(
											item,
											singleDataSetField,
											allCodeList,
											tempChartSetDataItem,
											groupField
										);
									}
								);
							}
						} else {
							// 序列属性存在时
							// 序列代码表存在时,翻译tempSeriesValues的键值对
							if (singleSeries.seriesCodeList) {
								const seriesCodeList: Map<string, any> = allCodeList.get(
									singleSeries.seriesCodeList.tag
								);
								let tempSeriesValueItem = tempSeriesValues.get(
									seriesCodeList.get(item[singleSeries.seriesIdField])
								);
								if (!tempSeriesValueItem) {
									tempSeriesValues.set(
										seriesCodeList.get(item[singleSeries.seriesIdField]),
										seriesCodeList.get(item[singleSeries.seriesNameField])
									);
								}
							} else {
								let tempSeriesValueItem = tempSeriesValues.get(
									item[singleSeries.seriesIdField]
								);
								if (!tempSeriesValueItem) {
									tempSeriesValues.set(
										item[singleSeries.seriesIdField],
										item[singleSeries.seriesNameField]
									);
								}
							}
							Object.assign(tempChartSetDataItem, {
								name: item[singleSeries.seriesIdField],
							});
							if (
								singleSeries.dataSetFields &&
								singleSeries.dataSetFields.length > 0
							) {
								singleSeries.dataSetFields.forEach(
									(singleDataSetField: any) => {
										this.handleSingleDataSetField(
											item,
											singleDataSetField,
											allCodeList,
											tempChartSetDataItem,
											groupField
										);
									}
								);
							}
						}
						tempChartSetData.push(tempChartSetDataItem);
					});
					// 补全数据集合
					this.completeDataSet(tempChartSetData, singleSeries, allCodeList);
					// 序列代码表存在时,补全序列
					if (singleSeries.seriesCodeList) {
						const seriesCodeList: Map<string, any> = allCodeList.get(
							singleSeries.seriesCodeList.tag
						);
						tempSeriesValues = new Map();
						seriesCodeList?.forEach((item: any) => {
							tempSeriesValues.set(item, item);
						});
					}
					singleSeries.seriesValues = [...tempSeriesValues.keys()];
					let tempSeriesMapObj: any = {};
					tempSeriesValues.forEach((value: any, key: any) => {
						tempSeriesMapObj[key] = value;
					});
					singleSeries.seriesMap = tempSeriesMapObj;
					let callbackFunction: any =
						index === Object.values(this.seriesModel).length - 1
							? callback
							: null;
					// 往图表序列里塞data
					this.transformToChartSeriesDataSet(
						tempChartSetData,
						singleSeries,
						callbackFunction,
						allCodeList
					);
				}
			);
		}
	}

	/**
	 * 处理单个属性
	 *
	 * @param {*} input 输入值
	 * @param {*} field 属性值
	 * @param {*} allCodeList 所有代码表
	 * @param {*} result 结果值
	 * @param {*} groupField 分组属性
	 *
	 * @memberof ChartController
	 */
	public handleSingleDataSetField(
		input: any,
		field: any,
		allCodeList: any,
		result: any,
		groupField: any
	) {
		let tempFieldObj: any = {};
		//存在代码表的情况(自动转化值)
		if (field.codelist) {
			//获取代码表
			let curCodeList: Map<number, any> = allCodeList.get(
				field.codelist.codeName
			);
			tempFieldObj[field.name] = curCodeList.get(input[field.name]);
			tempFieldObj[field.name + '_srfvalue'] = input[field.name];
		} else {
			// 不存在代码表的情况
			if (groupField && Object.is(groupField.name, field.name)) {
				if (Object.is(groupField.groupMode, 'YEAR')) {
					tempFieldObj[field.name] = moment(input[field.name])
						.year()
						.toString();
				} else if (Object.is(groupField.groupMode, 'QUARTER')) {
					tempFieldObj[field.name] =
						moment(input[field.name]).year().toString() +
						'-' +
						moment(input[field.name]).quarters().toString();
				} else if (Object.is(groupField.groupMode, 'MONTH')) {
					tempFieldObj[field.name] =
						moment(input[field.name]).year().toString() +
						'-' +
						moment(input[field.name]).month().toString();
				} else if (Object.is(groupField.groupMode, 'YEARWEEK')) {
					tempFieldObj[field.name] =
						moment(input[field.name]).year().toString() +
						'-' +
						moment(input[field.name]).week().toString();
				} else if (Object.is(groupField.groupMode, 'DAY')) {
					tempFieldObj[field.name] = moment(input[field.name]).format(
						'YYYY-MM-DD'
					);
				} else {
					tempFieldObj[field.name] = input[field.name];
				}
			} else {
				if (!field.isCodeItem) {
					tempFieldObj[field.name] = input[field.name];
				}
			}
		}
		Object.assign(result, tempFieldObj);
	}

	/**
	 * 补全数据集
	 *
	 * @param {Array<any>} data 传入数据
	 * @param {Array<any>} item 单个序列
	 * @param {Array<any>} allCodeList 所有的代码表
	 *
	 * @memberof ChartController
	 */
	public completeDataSet(data: any, item: any, allCodeList: any) {
		// 分组属性
		let groupField = item.dataSetFields.find((datasetField: any) => {
			return datasetField.name === item.categorField;
		});
		if (!groupField || Object.is(groupField.groupMode, '')) {
			return;
		}
		//分组模式为代码表（补值）
		if (Object.is(groupField.groupMode, 'CODELIST')) {
			this.completeCodeList(data, item, allCodeList);
		}
		//分组模式为年/季度/月份（最大值，最小值，分组，补值）
		if (
			Object.is(groupField.groupMode, 'YEAR') ||
			Object.is(groupField.groupMode, 'QUARTER') ||
			Object.is(groupField.groupMode, 'MONTH') ||
			Object.is(groupField.groupMode, 'YEARWEEK') ||
			Object.is(groupField.groupMode, 'DAY')
		) {
			this.handleTimeData(data, item, allCodeList, groupField);
		}
	}

	/**
	 * 补全代码表
	 *
	 * @param {Array<any>} data 传入数据
	 * @param {Array<any>} item 单个序列
	 * @param {Array<any>} allCodeList 所有的代码表
	 *
	 * @memberof ChartController
	 */
	public completeCodeList(data: any, item: any, allCodeList: any) {
		let groupField = item.dataSetFields.find((datasetField: any) => {
			return datasetField.name === item.categorField;
		});
		if (!groupField.codelist) {
			return;
		}
		let valueField = item.dataSetFields.find((datasetField: any) => {
			return datasetField.name === item.valueField;
		});
		let curCodeList: Map<number, any> = allCodeList.get(
			groupField.codelist.codeName
		);
		// 对分类实现分组
		let tempGroupData: Map<string, any> = new Map();
		data.forEach((item: any) => {
			let tempGroupItem: any = tempGroupData.get(
				item[groupField.name + '_srfvalue']
			);
			if (!tempGroupItem) {
				tempGroupData.set(item[groupField.name + '_srfvalue'], item);
			}
		});
		if (curCodeList.size !== tempGroupData.size) {
			curCodeList.forEach((text: any, value: any) => {
				if (!tempGroupData.get(value)) {
					let copyTemp: any = deepCopy(data[0]);
					let curObj: any = {};
					curObj[groupField.name + '_srfvalue'] = value;
					curObj[groupField.name] = text;
					curObj[valueField.name] = 0;
					Object.assign(copyTemp, curObj);
					data.push(copyTemp);
				}
			});
		}
	}

	/**
	 * 补全时间类型数据集
	 *
	 * @param {Array<any>} data 传入数据
	 * @param {Array<any>} item 单个序列
	 * @param {Array<any>} allCodeList 所有的代码表
	 * @param {Array<any>} groupField 分组属性
	 *
	 * @memberof ChartController
	 */
	public handleTimeData(
		data: any,
		item: any,
		allCodeList: any,
		groupField: any
	) {
		let valueField = item.dataSetFields.find((datasetField: any) => {
			return datasetField.name === item.valueField;
		});
		let groupMode: string = groupField.groupMode;
		// 排序数据，找到最大值、最小值
		let tempTimeArray: Array<any> = [];
		if (data && data.length > 0) {
			data.forEach((dataItem: any) => {
				// 判断时间类型是否为空，为空不处理
				if (dataItem[groupField.name]) {
					tempTimeArray.push(moment(dataItem[groupField.name]));
				}
			});
		}
		let maxTime: any;
		let minTime: any;
		if (Object.is(groupMode, 'YEAR') || Object.is(groupMode, 'DAY')) {
			maxTime = moment.max(tempTimeArray);
			minTime = moment.min(tempTimeArray);
		}
		if (Object.is(groupMode, 'QUARTER')) {
			tempTimeArray = this.getRangeData(tempTimeArray);
			minTime = moment()
				.year(tempTimeArray[0]._i.split('-')[0])
				.quarters(tempTimeArray[0]._i.split('-')[1]);
			maxTime = moment()
				.year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
				.quarters(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
		}
		if (Object.is(groupMode, 'MONTH')) {
			tempTimeArray = this.getRangeData(tempTimeArray);
			minTime = moment()
				.year(tempTimeArray[0]._i.split('-')[0])
				.month(tempTimeArray[0]._i.split('-')[1]);
			maxTime = moment()
				.year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
				.month(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
		}
		if (Object.is(groupMode, 'YEARWEEK')) {
			tempTimeArray = this.getRangeData(tempTimeArray);
			minTime = moment()
				.year(tempTimeArray[0]._i.split('-')[0])
				.week(tempTimeArray[0]._i.split('-')[1]);
			maxTime = moment()
				.year(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[0])
				.week(tempTimeArray[tempTimeArray.length - 1]._i.split('-')[1]);
		}
		let timeFragmentArray: Array<any> = [];
		let tempGroupData: Map<string, any> = new Map();
		// 时间分段
		//groupMode为"YEAR"
		if (Object.is(groupMode, 'YEAR')) {
			let curTime: any = minTime;
			while (curTime) {
				if (curTime.isSameOrBefore(maxTime)) {
					let tempCurTime: any = curTime.clone();
					timeFragmentArray.push(tempCurTime.year().toString());
					curTime = tempCurTime.clone().add(1, 'years');
				} else {
					curTime = null;
				}
			}
		}
		//groupMode为"QUARTER"
		if (Object.is(groupMode, 'QUARTER')) {
			let curTime: any = minTime;
			while (curTime) {
				if (curTime.isSameOrBefore(maxTime)) {
					let tempCurTime: any = curTime.clone();
					timeFragmentArray.push(
						tempCurTime.year().toString() +
							'-' +
							tempCurTime.quarter().toString()
					);
					curTime = tempCurTime.clone().add(1, 'quarters');
				} else {
					curTime = null;
				}
			}
		}
		//groupMode为"MONTH"
		if (Object.is(groupMode, 'MONTH')) {
			let curTime: any = minTime;
			while (curTime) {
				if (curTime.isSameOrBefore(maxTime)) {
					let tempCurTime: any = curTime.clone();
					timeFragmentArray.push(
						tempCurTime.year().toString() + '-' + tempCurTime.month().toString()
					);
					curTime = tempCurTime.clone().add(1, 'months');
				} else {
					curTime = null;
				}
			}
		}
		//groupMode为"YEARWEEK"
		if (Object.is(groupMode, 'YEARWEEK')) {
			let curTime: any = minTime;
			while (curTime) {
				if (curTime.isSameOrBefore(maxTime)) {
					let tempCurTime: any = curTime.clone();
					timeFragmentArray.push(
						tempCurTime.year().toString() + '-' + tempCurTime.week().toString()
					);
					curTime = tempCurTime.clone().add(1, 'weeks');
				} else {
					curTime = null;
				}
			}
		}
		//groupMode为"DAY"
		if (Object.is(groupMode, 'DAY')) {
			let curTime: any = minTime;
			while (curTime) {
				if (curTime.isSameOrBefore(maxTime)) {
					let tempCurTime: any = curTime.clone();
					timeFragmentArray.push(tempCurTime.format('YYYY-MM-DD'));
					curTime = tempCurTime.clone().add(1, 'days');
				} else {
					curTime = null;
				}
			}
		}
		data.forEach((item: any) => {
			let tempKeyStr: string = item[groupField.name];
			let tempGroupItem: any = tempGroupData.get(tempKeyStr);
			if (!tempGroupItem) {
				tempGroupData.set(tempKeyStr, item);
			}
		});
		timeFragmentArray.forEach((timeFragment: any) => {
			if (!tempGroupData.get(timeFragment)) {
				let copyTemp: any = deepCopy(data[0]);
				let curObj: any = {};
				curObj[groupField.name] = timeFragment;
				curObj[valueField.name] = 0;
				Object.assign(copyTemp, curObj);
				data.push(copyTemp);
			}
		});
	}

	/**
	 * 获取最大值最小值
	 *
	 * @param {Array<any>} tempTimeArray 传入数据
	 *
	 * @memberof ChartController
	 */
	public getRangeData(tempTimeArray: Array<any>) {
		tempTimeArray.forEach((item: any) => {
			let tempParams: Array<any> = item._i.split('-');
			item.sortField = Number(tempParams[0] + tempParams[1]);
		});
		tempTimeArray.sort((a: any, b: any) => {
			return Number(a.sortField) - Number(b.sortField);
		});
		tempTimeArray.forEach((item: any) => {
			delete item.sortField;
		});
		return tempTimeArray;
	}

	/**
	 * 构建图表序列数据集合
	 *
	 * 1.分组求和
	 * 2.排序求和数组
	 *
	 * @param {Array<any>} data 传入数据
	 * @param {Array<any>} item 单个序列
	 * @param {Array<any>} callback 回调
	 * @param {*} allCodeList 所有代码表
	 *
	 * @memberof ChartController
	 */
	public transformToChartSeriesDataSet(
		data: any,
		item: any,
		callback: Function,
		allCodeList: any
	): any {
		if (item.seriesIdField) {
			// 多序列
			let groupField = item.dataSetFields.filter((datasetField: any) => {
				return datasetField.name === item.categorField;
			});
			let tempGroupField: Array<any> = groupField.map((item: any) => {
				return item.name;
			});
			let seriesField = item.dataSetFields.filter((datasetField: any) => {
				return datasetField.name === item.seriesIdField;
			});
			let tempSeriesField: Array<any> = seriesField.map((item: any) => {
				return item.name;
			});
			let valueField = item.dataSetFields.filter((datasetField: any) => {
				return datasetField.name === item.valueField;
			});
			let tempValueField: Array<any> = valueField.map((item: any) => {
				return item.name;
			});
			item.data = this.groupAndAdd(
				tempGroupField,
				tempSeriesField,
				tempValueField,
				data,
				item,
				groupField,
				allCodeList
			);
		} else {
			//单序列
			let groupField = item.dataSetFields.filter((datasetField: any) => {
				return datasetField.name === item.categorField;
			});
			let tempGroupField: Array<any> = groupField.map((item: any) => {
				return item.name;
			});
			let valueField = item.dataSetFields.filter((datasetField: any) => {
				return datasetField.name === item.valueField;
			});
			let tempValueField: Array<any> = valueField.map((item: any) => {
				return item.name;
			});
			item.data = this.groupAndAdd(
				tempGroupField,
				[],
				tempValueField,
				data,
				item,
				groupField,
				allCodeList
			);
		}
		if (callback && callback instanceof Function) {
			callback(allCodeList);
		}
	}

	/**
	 * 分组和求和
	 *
	 * @param {Array<any>} groupField 分组属性
	 * @param {Array<any>} seriesField 序列属性
	 * @param {Array<any>} valueField 值属性
	 * @param {*} data 传入数据
	 * @param {*} item 单个序列
	 * @param {*} groupFieldModel 分组属性模型
	 * @param {*} allCodeList 所有代码表
	 * @return {*}
	 * @memberof ChartController
	 */
	public groupAndAdd(
		groupField: Array<any>,
		seriesField: Array<any>,
		valueField: Array<any>,
		data: any,
		item: any,
		groupFieldModel: any,
		allCodeList: any
	) {
		let tempMap: Map<string, any> = new Map();
		// let groupMode: string = groupFieldModel[0].groupMode;
		let groupKeyStr: string = '';
		data.forEach((item: any) => {
			let tempGroupField: string = groupField[0];
			groupKeyStr = item[tempGroupField];
			let tempMapItem: any = tempMap.get(groupKeyStr);
			if (tempMapItem) {
				tempMapItem.push(item);
				tempMap.set(groupKeyStr, tempMapItem);
			} else {
				tempMap.set(groupKeyStr, [item]);
			}
		});
		// 处理多序列
		if (seriesField.length > 0 && tempMap.size > 0) {
			let tempSeriesField: string = seriesField[0];
			tempMap.forEach((item: any, key: string) => {
				let tempItemMap: Map<string, any> = new Map();
				item.forEach((singleItem: any) => {
					let seriesValueArray: any = tempItemMap.get(
						singleItem[tempSeriesField]
					);
					if (seriesValueArray) {
						seriesValueArray.push(singleItem);
						tempItemMap.set(singleItem[tempSeriesField], seriesValueArray);
					} else {
						tempItemMap.set(singleItem[tempSeriesField], [singleItem]);
					}
				});
				tempMap.set(key, tempItemMap);
			});
		}
		let returnArray: Array<any> = [];
		if (seriesField.length == 0) {
			//单序列
			tempMap.forEach((tempItem: any) => {
				if (tempItem.length > 0) {
					let curObject: any = {};
					let valueResult: any = {};
					let categorResult: any;
					tempItem.forEach((singleItem: any) => {
						categorResult = singleItem[groupField[0]];
						valueResult[valueField[0]] = valueResult[valueField[0]]
							? singleItem[valueField[0]]
								? valueResult[valueField[0]] + singleItem[valueField[0]]
								: valueResult[valueField[0]]
							: singleItem[valueField[0]];
						item.dataSetFields.forEach((dataSetField: any) => {
							// 只读不合并数据（扩展值属性4）
							if (dataSetField.isReadOnly) {
								valueResult[dataSetField.name] = singleItem[dataSetField.name];
							} else {
								if (
									!Object.is(dataSetField.name, groupField[0]) &&
									!Object.is(dataSetField.name, valueField[0])
								) {
									valueResult[dataSetField.name] = valueResult[
										dataSetField.name
									]
										? valueResult[dataSetField.name] +
										  singleItem[dataSetField.name]
										: singleItem[dataSetField.name];
								}
							}
						});
					});
					Object.defineProperty(curObject, groupField[0], {
						value: categorResult,
						writable: true,
						enumerable: true,
						configurable: true,
					});
					for (const value in valueResult) {
						Object.defineProperty(curObject, value, {
							value: valueResult[value],
							writable: true,
							enumerable: true,
							configurable: true,
						});
					}
					returnArray.push(curObject);
				}
			});
		} else {
			// 多序列
			let seriesValuesArray: Array<any> = item.seriesValues;
			tempMap.forEach((groupItem: any, groupKey: string) => {
				//求和
				let curObject: any = {};
				Object.defineProperty(curObject, groupField[0], {
					value: groupKey,
					writable: true,
					enumerable: true,
					configurable: true,
				});
				seriesValuesArray.forEach((seriesValueItem: any) => {
					Object.defineProperty(curObject, seriesValueItem, {
						value: 0,
						writable: true,
						enumerable: true,
						configurable: true,
					});
				});
				groupItem.forEach((seriesItem: any, seriesKey: string) => {
					let seriesNum: number = 0;
					seriesItem.forEach((dataItem: any) => {
						seriesNum += dataItem[valueField[0]];
					});
					curObject[seriesKey] = seriesNum;
				});
				returnArray.push(curObject);
			});
		}
		// 补全空白分类
		if (returnArray.length > 0) {
			let emptyText =
				groupFieldModel[0] && groupFieldModel[0].codeList
					? groupFieldModel[0].codeList.emptytext
					: App.ts('app.warn.undefined', '未定义');
			returnArray.forEach((item: any) => {
				if (!item[groupField[0]]) {
					item[groupField[0]] = emptyText;
				}
			});
		}
		returnArray = this.sortReturnArray(
			returnArray,
			groupFieldModel,
			allCodeList
		);
		// 雷达图数据格式处理
		if (Object.is(item.type, 'radar') && returnArray.length > 0) {
			let tempReturnArray: Array<any> = [];
			let seriesValues: Array<any> = item.seriesValues;
			if (seriesValues && seriesValues.length > 0) {
				seriesValues.forEach((singleSeriesName: any) => {
					let singleSeriesObj: any = {};
					returnArray.forEach((item: any) => {
						Object.assign(singleSeriesObj, {
							[item[groupField[0]]]: item[singleSeriesName],
						});
					});
					Object.assign(singleSeriesObj, { type: singleSeriesName });
					tempReturnArray.push(singleSeriesObj);
				});
			}
			returnArray = tempReturnArray;
		}
		return returnArray;
	}

	/**
	 * 排序数组
	 *
	 * @param {Array<any>} arr 传入数组
	 * @param {*} groupField 分组属性
	 * @param {*} allCodeList 所有代码表
	 *
	 * @memberof ChartController
	 */
	public sortReturnArray(arr: Array<any>, groupField: any, allCodeList: any) {
		let returnArray: Array<any> = [];
		// 分组属性有代码表的情况(最后执行)
		if (groupField[0].codelist) {
			let curCodeList: Map<number, any> = allCodeList.get(
				groupField[0].codelist.codeName
			);
			curCodeList.forEach((codelist: any) => {
				arr.forEach((item: any) => {
					if (Object.is(item[groupField[0].name], codelist)) {
						returnArray.push(item);
						item.hasused = true;
					}
				});
			});
			arr.forEach((item: any, index: number) => {
				if (!item.hasused) {
					returnArray.push(item);
				}
			});
			returnArray.forEach((item: any) => {
				delete item.hasused;
			});
		} else {
			// 分组为年份
			if (Object.is(groupField[0].groupMode, 'YEAR')) {
				returnArray = arr.sort((a: any, b: any) => {
					return Number(a[groupField[0].name]) - Number(b[groupField[0].name]);
				});
			} else if (Object.is(groupField[0].groupMode, 'QUARTER')) {
				returnArray = this.handleSortGroupData(
					arr,
					groupField,
					'季度' as string
				);
			} else if (Object.is(groupField[0].groupMode, 'MONTH')) {
				returnArray = this.handleSortGroupData(arr, groupField, '月' as string);
			} else if (Object.is(groupField[0].groupMode, 'YEARWEEK')) {
				returnArray = this.handleSortGroupData(arr, groupField, '周' as string);
			} else if (Object.is(groupField[0].groupMode, 'DAY')) {
				returnArray = arr.sort((a: any, b: any) => {
					return (
						moment(a[groupField[0].name]).unix() -
						moment(b[groupField[0].name]).unix()
					);
				});
			} else {
				let groupFieldName: string = groupField[0].name;
				let isConvert: boolean = true;
				arr.forEach((item: any) => {
					if (isNaN(item[groupFieldName])) {
						isConvert = false;
					}
				});
				if (isConvert) {
					returnArray = arr.sort((a: any, b: any) => {
						return a[groupFieldName] - b[groupFieldName];
					});
				} else {
					returnArray = arr;
				}
			}
		}
		return returnArray;
	}

	/**
	 * 排序分组模式下的数据
	 *
	 * @param {Array<any>} arr 传入数据
	 * @param {Array<any>} groupField 分组属性
	 * @param {Array<any>} label label标签
	 *
	 * @memberof ChartController
	 */
	public handleSortGroupData(arr: Array<any>, groupField: any, label: string) {
		arr.forEach((item: any) => {
			let sortFieldValue: Array<any> = item[groupField[0].name].split('-');
			Object.assign(item, {
				sortField:
					Number(sortFieldValue[0]) * 10000 + Number(sortFieldValue[1]),
			});
			if (Object.is(label, '月')) {
				item[groupField[0].name] =
					sortFieldValue[0] +
					('年' as string) +
					(Number(sortFieldValue[1]) + 1) +
					label;
			} else {
				item[groupField[0].name] =
					sortFieldValue[0] + ('年' as string) + sortFieldValue[1] + label;
			}
		});
		arr.sort((a: any, b: any) => {
			return Number(a.sortField) - Number(b.sortField);
		});
		arr.forEach((item: any) => {
			delete item.sortField;
		});
		return arr;
	}

	/**
	 * 初始化seriesModel
	 *
	 * @memberof ChartController
	 */
	public async initSeriesModel() {
		if (!this.model.serieses) {
			return;
		}
		for (let index = 0; index < this.model.serieses.length; index++) {
			const series = this.model.serieses[index];
			if (series) {
				this.seriesModel[series.name.toLowerCase()] =
					this.getSeriesModelParam(series);
			}
		}
	}

	/**
	 * 获取SeriesModel参数
	 *
	 * @param {*} series 序列模型
	 * @memberof ChartController
	 */
	public getSeriesModelParam(series: any): Promise<any> {
		this.chartValueName = series.valueField;
		this.chartCatalogName = series.catalogField;
		// 构造dataSetFields属性
		const opts: any = {
			name: series.name,
			categorField: series.catalogField,
			valueField: series.valueField,
			seriesValues: [],
			seriesIndex: series.index | 0,
			data: [],
			seriesMap: {},
			categorCodeList: series.categorCodeList,
			dataSetFields: this.getDataSetFields(series),
			ecxObject: {
				label: {
					show: true,
					position: 'top',
				},
				labelLine: {
					length: 10,
					lineStyle: {
						width: 1,
						type: 'solid',
					},
				},
				itemStyle: {
					borderWidth: 1,
				},
				emphasis: {
					label: {
						show: true,
						fontSize: 20,
					},
				},
			},
			seriesCodeList: series.seriesCodeList,
			seriesNameField: series.seriesField,
			seriesIdField: series.seriesField,
			ecObject: {},
			seriesTemp: {
				type: series.eChartsType,
			},
			type: series.eChartsType,
			seriesLayoutBy: series.seriesLayoutBy,
			baseOption: {},
		};
		// 饼图引导线默认配置
		if (Object.is(series.eChartsType, 'pie')) {
			Object.assign(opts.ecxObject.label, {
				position: 'outside',
				formatter: `{b}: {d}%({@${opts.valueField}})`,
			});
			Object.assign(opts.ecxObject.labelLine, {
				show: true,
			});
		}
		// 漏斗图默认配置
		if (Object.is(series.eChartsType, 'funnel')) {
			Object.assign(opts.ecxObject.label, {
				position: 'outside',
				formatter: `{b}: {d}%({@${opts.valueField}})`,
			});
		}
		// 地图默认配置（暂时自定义）
		if (Object.is(series.eChartsType, 'custom')) {
			Object.assign(opts.ecxObject.label, {
				formatter: `{b}: {@${opts.valueField}}`,
			});
			opts.ecxObject.tooltip = {
				trigger: 'item',
				formatter: '{b}:  {c}',
			};
		}
		// 处理自定义ECX参数
		this.fillUserParam(series, opts.ecxObject, 'ECX');
		this.fillUserParam(series, opts.ecObject, 'EC');
		Object.assign(
			opts,
			series.baseOptionJOString
				? new Function('return {' + series.baseOptionJOString + '}')()
				: {}
		);

		return opts;
	}

	/**
	 * 临时获取seriesDataSetField 模型
	 *
	 * @param {*} series 序列模型
	 * @return {*}
	 * @memberof ChartController
	 */
	public getDataSetFields(series: any) {
		const seriesData: any = [];
		const dataSet =
			this.model.dataSets?.find((item: any) => {
				return item.id === series.chartDataSetId;
			}) || null;
		if (!dataSet && !dataSet.fields) {
			return null;
		}
		for (let index = 0; index < dataSet.fields?.length; index++) {
			const dataFile: any = dataSet.fields[index];
			const data: any = {};
			if (dataFile.codelist) {
				const codeList = dataFile.codelist;
				Object.assign(data, { codelist: codeList });
				// 设置代码项原值
				if (Object.is(dataFile?.name, series?.catalogField)) {
					const tempCodeItem = {
						name: `${dataFile.name}_srfvalue`,
						isGroupField: dataFile.groupField,
						groupMode: dataFile.groupMode,
						isReadOnly: true,
						isCodeItem: true,
					};
					seriesData.push(tempCodeItem);
				}
			}
			data['isGroupField'] = dataFile.groupField;
			data['name'] = dataFile.name;
			data['groupMode'] = dataFile.groupMode;
			// 只读不合并数据（扩展值属性4）
			if (
				series.extValue4Field &&
				Object.is(dataFile.name, series.extValue4Field)
			) {
				data['isReadOnly'] = true;
			}
			seriesData.push(data);
		}
		return seriesData;
	}

	/**
	 * 是否为json字符串
	 *
	 * @param {*} str 字符串
	 * @return {*}  {boolean}
	 * @memberof ChartController
	 */
	public isJson(str: any): boolean {
		try {
			JSON.parse(str);
			return true;
		} catch (error) {
			return false;
		}
	}

	/**
	 * 解析字符串函数
	 *
	 * @param {*} data
	 * @return {*}  {boolean}
	 * @memberof ChartController
	 */
	public deepJsonParseFun(data: any): any {
		switch (typeof data) {
			case 'string':
			case 'number':
			case 'boolean':
			case 'undefined':
			case 'function':
			case 'symbol':
				return data;
		}
		for (const key in data) {
			const item = data[key];
			let res: any;
			if (item.isFun && item.functionBody) {
				res = new Function(item.arg, item.functionBody);
			} else {
				res = this.deepJsonParseFun(item);
			}
			data[key] = res;
		}
		return data;
	}

	/**
	 * 是否为数组字符串
	 *
	 * @param {string} str 字符串
	 * @return {*}
	 * @memberof ChartController
	 */
	public isArray(str: string) {
		try {
			eval(str);
			return true;
		} catch (error) {
			return false;
		}
	}

	/**
	 * 处理用户自定义参数
	 *
	 * @param {*} param 模型对象
	 * @param {*} opts 图表参数
	 * @param {string} tag 模式标识
	 * @return {*}
	 * @memberof ChartController
	 */
	public fillUserParam(param: any, opts: any, tag: string) {
		if (!param.userParams) {
			return;
		}
		const userParam = param.userParams;
		switch (tag) {
			case 'ECX':
				if (userParam['ECX.label']) {
					opts['label'] = eval('(' + userParam['ECX.label'] + ')');
				}
				if (userParam['ECX.labelLine']) {
					opts['labelLine'] = eval('(' + userParam['ECX.labelLine'] + ')');
				}
				if (userParam['ECX.itemStyle']) {
					opts['itemStyle'] = eval('(' + userParam['ECX.itemStyle'] + ')');
				}
				if (userParam['ECX.emphasis']) {
					opts['emphasis'] = eval('(' + userParam['ECX.emphasis'] + ')');
				}
				for (const key in userParam) {
					if (Object.prototype.hasOwnProperty.call(userParam, key)) {
						if (key.indexOf('EC.') != -1) {
							const value = userParam[key].trim();
							opts[key.replace('EC.', '')] = value;
						}
					}
				}
				break;
			case 'EC':
				for (const key in userParam) {
					if (Object.prototype.hasOwnProperty.call(userParam, key)) {
						if (key.indexOf('EC.') != -1) {
							const value = userParam[key].trim();
							opts[key.replace('EC.', '')] = this.isJson(value)
								? this.deepJsonParseFun(JSON.parse(value))
								: this.isArray(value)
								? eval(value)
								: value;
						}
					}
				}
				break;
			default:
				break;
		}
	}

	/**
	 * 填充chartOption
	 *
	 * @memberof ChartController
	 */
	public initChartOption() {
		const series: any = [];
		// 填充series
		const indicator: any = [];
		this.model.serieses?.forEach((_series: any) => {
			series.push(this.fillSeries(_series, indicator));
		});
		// 填充xAxis
		const xAxis: any = [];
		this.model.chartXAxises.forEach((_xAxis: any) => {
			xAxis.push(this.fillAxis(_xAxis));
		});
		// 填充yAxis
		const yAxis: any = [];
		this.model.chartYAxises?.forEach((_yAxis: any) => {
			yAxis.push(this.fillAxis(_yAxis));
		});
		// 填充grid
		const grid: any = [];
		this.model.chartGrids?.forEach((_grid: any) => {
			grid.push({
				...(_grid.baseOptionJOString
					? new Function('return {' + _grid.baseOptionJOString + '}')()
					: {}),
			});
		});
		// chartOption参数
		const opt = {
			tooltip: { show: true },
			dataset: [],
			series: series,
			xAxis: xAxis,
			yAxis: yAxis,
			// grid: grid,
		};
		this.fillTitleOption(opt);
		this.fillLegendOption(opt);
		// TODO 地图暂不支持
		// this.registerMap();
		// 合并chartOption
		Object.assign(this.chartOption, opt);
		// 雷达图特殊参数
		if (indicator.length > 0) {
			Object.assign(this.chartOption, { radar: { indicator } });
		}
	}

	/**
	 * 数组元素小写
	 *
	 * @param {*} arr 数组
	 * @returns
	 * @memberof ChartController
	 */
	public arrayToLowerCase(arr: any) {
		if (!arr || arr.length == 0) {
			return [];
		}
		for (let index = 0; index < arr.length; index++) {
			arr[index] = arr[index].toLowerCase();
		}
		return arr;
	}

	/**
	 * 填充 series
	 *
	 * @param {*} series 序列模型
	 * @param {*} [indicator={}] 雷达图参数
	 * @return {*}
	 * @memberof ChartController
	 */
	public fillSeries(series: any, indicator: any = {}) {
		const encode: any = {};
		let customType: string = '';
		const assginCodeList = (codeList: any) => {
			codeList.codeItems?.forEach((_item: any) => {
				let item: any = {
					name: _item.text,
					max: _item.userParams?.MAXVALUE ? _item.userParams.MAXVALUE : null,
				};
				indicator.push(item);
				if (_item.codeItems?.length > 0) {
					assginCodeList(_item);
				}
			});
		};
		switch (series.eChartsType) {
			case 'line':
			case 'bar':
				const cSCartesian2DEncode = series.chartSeriesEncode;
				encode.x = this.arrayToLowerCase(cSCartesian2DEncode.getX);
				encode.y = this.arrayToLowerCase(cSCartesian2DEncode.getY);
				break;
			case 'pie':
			case 'funnel':
				const CSNoneEncode = series.chartSeriesEncode;
				encode.itemName = CSNoneEncode.category?.toLowerCase();
				encode.value = CSNoneEncode.value?.toLowerCase();
				break;
			case 'radar':
				encode.itemName = 'type';
				const catalogCodeList = series.categorCodeList;
				if (catalogCodeList) {
					assginCodeList(catalogCodeList);
				}
				break;
			case 'scatter':
				break;
			case 'gauge':
				break;
			case 'candlestick':
				const candlestickEncode = series.chartSeriesEncode;
				encode.x = this.arrayToLowerCase(candlestickEncode.getX);
				encode.y = this.arrayToLowerCase(candlestickEncode.getY);
				break;
			case 'custom':
				customType = 'map';
				break;
			default:
				break;
		}
		return {
			id: series.name?.toLowerCase(),
			name: App.ts(series.capPSLanguageRes, series.caption),
			type: customType ? customType : series.eChartsType,
			xAxisIndex: series.xAxisIndex | 0,
			yAxisIndex: series.yAxisIndex | 0,
			datasetIndex: series.chartDataSetId | 0,
			encode: Object.keys(encode).length > 0 ? encode : null,
			areaStyle: series.seriesType === 'area' ? {} : null,
			...(series.baseOptionJOString
				? new Function('return {' + series.baseOptionJOString + '}')()
				: {}),
		};
	}

	/**
	 * 填充 axis
	 *
	 * @param {IPSChartGridXAxis} axis 坐标模型
	 * @return {*}  {*}
	 * @memberof ChartController
	 */
	public fillAxis(axis: any): any {
		const _axis: any = {
			position: axis.position,
			type: axis.eChartsType,
			name: App.ts(axis.capPSLanguageRes, axis.caption),
		};
		const dataShowMode = (axis as any).dataShowMode;
		if (dataShowMode === 1) {
			//  纵向显示
			Object.assign(_axis, {
				axisLabel: {
					formatter: (value: any) => {
						if (value.length > 4) {
							return value.substr(0, 4).split('').join('\n') + '\n...';
						} else {
							return value.split('').join('\n');
						}
					},
				},
			});
		} else if (dataShowMode === 2) {
			//  横向显示
		} else if (dataShowMode === 3) {
			//  斜向显示
			Object.assign(_axis, {
				axisLabel: {
					rotate: 45,
					formatter: (value: any) => {
						if (value.length > 4) {
							return value.substr(0, 4) + '...';
						} else {
							return value;
						}
					},
				},
			});
		}
		// 填充用户自定义参数
		this.fillUserParam(axis, _axis, 'EC');
		if (axis.minValue) {
			_axis['min'] = axis.minValue;
		}
		if (axis.maxValue) {
			_axis['max'] = axis.maxValue;
		}
		return _axis;
	}

	/**
	 * 填充标题配置
	 *
	 * @param opts 图表配置
	 * @memberof ChartController
	 */
	public fillTitleOption(opts: any) {
		if (this.model.chartTitle) {
			const _titleModel = this.model.chartTitle;
			let title: any = {
				show: _titleModel?.showTitle,
				text: App.ts(_titleModel?.titlePSLanguageRes, _titleModel?.title),
				subtext: App.ts(
					_titleModel?.subTitlePSLanguageRes,
					_titleModel?.subTitle
				),
			};
			if (_titleModel?.titlePos) {
				switch (_titleModel?.titlePos) {
					case 'LEFT':
						Object.assign(title, {
							left: 'left',
						});
						break;
					case 'RIGHT':
						Object.assign(title, {
							left: 'right',
						});
						break;
					case 'BOTTOM':
						Object.assign(title, {
							left: 'center',
							top: 'bottom',
						});
						break;
				}
			}
			Object.assign(opts, { title });
		}
	}

	/**
	 * 填充图例配置
	 *
	 * @param opts 图表配置
	 * @memberof ChartController
	 */
	public fillLegendOption(opts: any) {
		if (this.model.chartLegend) {
			const legendModel: any = this.model.chartLegend;
			let legend: any = {
				show: legendModel?.showLegend,
			};
			if (legendModel?.legendPos) {
				switch (legendModel.legendPos) {
					case 'LEFT':
						Object.assign(legend, {
							left: 'left',
							top: 'middle',
							orient: 'vertical',
						});
						break;
					case 'RIGHT':
						Object.assign(legend, {
							left: 'right',
							top: 'middle',
							orient: 'vertical',
						});
						break;
					case 'BOTTOM':
						Object.assign(legend, {
							top: 'bottom',
						});
						break;
				}
			}
			Object.assign(opts, { legend });
		}
	}

	/**
	 * 初始化chartUserParams
	 *
	 * @memberof ChartController
	 */
	public initChartUserParams() {
		this.fillUserParam(this.model, this.chartUserParams, 'EC');
	}

	/**
	 * 初始化图表基础动态模型
	 *
	 * @memberof ChartController
	 */
	public initChartBaseOPtion() {
		if (this.model.baseOptionJOString) {
			this.chartBaseOPtion = new Function(
				'return {' + this.model.baseOptionJOString + '}'
			)();
		}
	}

	/**
	 * 更新图表大小
	 *
	 * @memberof ChartController
	 */
	public updateSize() {
		if (
			this.myChart &&
			this.myChart.resize &&
			this.myChart.resize instanceof Function
		) {
			this.myChart.resize();
		}
	}

	/**
	 * 获取能力
	 *
	 * @template A
	 * @return {*}  {A}
	 * @memberof ChartController
	 */
	getAbility(): IChartAbility {
		return {
			...super.getAbility(),
			updateSize: this.updateSize.bind(this),
		};
	}

	/**
	 * Creates an instance of ChartController.
	 * @param {IChartControllerParams} params
	 * @memberof ChartController
	 */
	public constructor(
		params: IChartControllerParams<ChartActionType, IChartAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}
}
